
import EnvConfig from "../config/EnvConfig"
import { cacheOfUnitNameRel } from "../config/UnitBaseAttrConfig";
import { AttachPointsType, DmgTypeKey } from "../types/L_Type";
import { DAMAGE_TYPE_NORMAL, UNIT_STATE_LIFE, WEAPON_TYPE_WHOKNOWS } from "../types/define";
import L_Math from "./L_Math";
import LuaTimer from "./LuaTimer";



export default class L_Run{

    static errorInfo(msg:string,allPlayer?:boolean){
        if(!EnvConfig.devMod) {
            if(allPlayer){
                for(let i=0;i<EnvConfig.playerNums;i++){
                    DisplayTextToPlayer(Player(i), 0, 0, "|Cffff0000【ERROR】"+msg)
                }
            }else{
              DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "|Cffff0000【ERROR】"+msg)
            }
        }
        console.log("【ERROR】",msg)
    }

    static KillUnit_L(u:unit){
        if(!EnvConfig.devMod) {
            KillUnit(u) 
        }
        console.log("模拟杀死箭矢马甲")
    }
  
    static isEnemy(aunit:unit,bunit:unit):boolean{
        if(!EnvConfig.devMod) {
            return  GetOwningPlayer(GetFilterUnit()) != GetOwningPlayer(aunit)  &&  !IsUnitAlly(GetFilterUnit(), GetOwningPlayer(aunit))
        }
        return true
    }

    private static isUnitAlive_L (whichUnit:unit):boolean{
        if(!EnvConfig.devMod) {
            return GetUnitState(whichUnit, UNIT_STATE_LIFE()) <= 0.3
        }
        return true
    } 

    /**
     * 创建一个单位在指定单位位置 一般指召唤物
     * @param whichUnit 
     * @param unitIdStr 
     * @param facing 
     * @returns 
     */
    public static createUnitAtUnitXY(whichUnit:unit,unitIdStr:string,facing?:number):any{
        if(!EnvConfig.devMod) {
            return CreateUnit(GetOwningPlayer(whichUnit), L_Math.ID2I(unitIdStr), GetUnitX(whichUnit), GetUnitY(whichUnit),facing || 0)
        }
        return 0
    }
   

        /**
     * 创建一个单位在指定位置
     * @param playerIndex  玩家索引号
     * @param unitIdStr 
     * @param x 
     * @param y 
     * @param facing 面对角度
     * @param testRsUnitHandle  测试模式下返回的指定单位句柄id
     * @returns 
     */
        public static createUnitAtXYByTypeName(playerIndex:number,typeName:string,x:number,y:number,facing?:number,testRsUnitHandle?:number):any{
            if(!EnvConfig.devMod) {
                let unitIdStr=cacheOfUnitNameRel(typeName)
                return CreateUnit(Player(playerIndex), L_Math.ID2I(unitIdStr), x, y,facing || 0)
            }
            return testRsUnitHandle || 0
        }
    /**
     * 创建一个单位在指定位置
     * @param playerIndex  玩家索引号
     * @param unitIdStr 
     * @param x 
     * @param y 
     * @param facing 面对角度
     * @param testRsUnitHandle  测试模式下返回的指定单位句柄id
     * @returns 
     */
    public static createUnitAtXY(playerIndex:number,unitIdStr:string,x:number,y:number,facing?:number,testRsUnitHandle?:number):any{
        if(!EnvConfig.devMod) {
            return CreateUnit(Player(playerIndex), L_Math.ID2I(unitIdStr), x, y,facing || 0)
        }
        return testRsUnitHandle || 0
    }


    /**
     * 判断选择单位是否敌人
     * @param aunit 攻击单位
     * @param funit 选择单位
     * @returns 
     */
    static enemyCpx(aunit:unit,funit:unit):boolean{
       return  ( GetOwningPlayer(aunit) != GetOwningPlayer(funit) ) && ( IsUnitAlly(aunit, GetOwningPlayer(funit)) == false ) &&  L_Run.isUnitAlive_L(funit) //&& ( IsUnitType(funit, UNIT_TYPE_STRUCTURE()) == false ) 
    
    }

    /**
     * 选择圆形区域内容单位执行动作
     * @param aunit 
     * @param x 
     * @param y 
     * @param radius 
     * @param callback 
     * @param isEnemy 
     */
    static getEnumUnitsInCircularToDoSomthing(aunit:unit,x:number,y:number,radius:number,callback:(u:unit)=>void,isEnemy?:boolean){
        if(!EnvConfig.devMod) {
            let gp=CreateGroup()
            GroupEnumUnitsInRange(gp, x, y, radius, Condition(()=>{
                return L_Run.isEnemy(GetFilterUnit(),aunit) &&  L_Run.isUnitAlive_L(GetFilterUnit()) 
                 }    
                ))
            let lflag=true    
            while(lflag){
                let tmp:unit=FirstOfGroup(gp)
                if(tmp==null){
                    lflag=false
                }else{
                    if(isEnemy ==undefined || isEnemy == L_Run.enemyCpx(aunit,tmp)){
                        callback(tmp)
                    }
                    GroupRemoveUnit(gp,tmp)
                }
            } 
            DestroyGroup(gp)   
        }else{
            //以下为测试用代码
            callback(aunit)
        }
    }


    static getDisOfUnitToXY(aunit:unit,targetX:number,targetY:number):number{
        if(!EnvConfig.devMod) {
            let  dx=GetUnitX(aunit)-targetX
            let  dy=GetUnitY(aunit)-targetY
            return SquareRoot(dx * dx + dy * dy)
        }
        return Math.sqrt(4)
    }

    static getDisOfUnit(aunit:unit,bunit:unit):number{
        if(!EnvConfig.devMod) {
            let  dx=GetUnitX(aunit)-GetUnitX(bunit)
            let  dy=GetUnitY(aunit)-GetUnitY(bunit)
            return SquareRoot(dx * dx + dy * dy)
        }
        return Math.sqrt(4)
    }


    static getDisOfCoordinate(startX:number,startY:number,targetX:number,targetY:number):number{
        let  dx=targetX - startX
        let  dy=targetY - startY
        if(!EnvConfig.devMod) {
            return SquareRoot(dx * dx + dy * dy)
        }
        return Math.sqrt(dx * dx + dy * dy)
    }

    static unitInDisBySimpleSts(aunit:unit,bunit:unit,dis:number):boolean{
        if(!EnvConfig.devMod) {
            return Math.abs(GetUnitX(aunit)-GetUnitX(bunit))<=dis || Math.abs(GetUnitY(aunit)-GetUnitY(bunit))<=dis
        }
        return true
    }

    static getAngleWithUnitToXY(aunit:unit,targetX:number,targetY:number):number{
        if(!EnvConfig.devMod) {
            return L_Run.getAngleWithLoc(GetUnitX(aunit),GetUnitY(aunit),targetX,targetY)
        }
        return L_Run.getAngleWithLoc(0,0,targetX,targetY)
    }

     /**两点坐标形成的角度 */
     static getAngleWithLoc(startX:number,startY:number,targetX:number,targetY:number):number{
        if(!EnvConfig.devMod) {
            return L_Math.getAngle(startX,startY,targetX,targetY)
        }
        return 10
    }


    /**两点坐标形成的角度 */
    static getAngleWithUnit(startUnit:unit,targetUnit:unit):number{
        if(!EnvConfig.devMod) {
            return L_Math.getAngle(GetUnitX(startUnit),GetUnitY(startUnit),GetUnitX(targetUnit),GetUnitY(targetUnit))
        }
        return 10
    }

    /**
     * 从单位的当前位置开始向角度angle移动dis码
     * @param u 
     * @param angle 
     * @param dis 
     */
    public static SetUnitXYToAgDis(u:unit,angle:number,dis:number):{x:number,y:number}{
        if(!EnvConfig.devMod) {
            let mx=GetUnitX(u) +  dis*Cos(angle * L_Math.BJ_DEGTORAD)
            SetUnitX(u,mx)
            let my=GetUnitY(u) +  dis*Sin(angle * L_Math.BJ_DEGTORAD)
            SetUnitY(u,my)
            return {'x':mx,'y':my}
        }
        return {x:0,y:0}
    }

    public static GetUnitX_L(u:unit):number{
        if(!EnvConfig.devMod) {
           return GetUnitX(u)
        } 
        return 1
    }

    public static GetUnitY_L(u:unit):number{
        if(!EnvConfig.devMod) {
           return GetUnitY(u)
        } 
        return 2
    }

    public static GetUnitPlayerIndex_L(u:unit):number{
        if(!EnvConfig.devMod) {
            LeaderboardGetPlayerIndex
            return GetPlayerId(GetOwningPlayer(u)) 
        } 
        return this.RandomInt_L(1,2)
    }

    public static initAllPlayerEvent(func:(playerIndex:number)=>void):void{
        for(let i=0;i<EnvConfig.playerNums;i++){
            func(i);
        }
    }

    /**dev环境替代GetHandleId方便测试 */
    public static GetHandleId_L(unitObj:any,dv?:number):number{
       if(!EnvConfig.devMod) return GetHandleId(unitObj)
       return dv || 90001 || GetHandleId(unitObj)
    }

    /**dev环境替代GetHandleId方便测试 */
    public static GetUnitName_L(unitObj:any,dv:string | undefined):string{
        if(!EnvConfig.devMod) return GetUnitName(unitObj)
        return dv || "测试单位" || GetUnitName(unitObj)
        }

    /**dev环境替代GetUnitTypeId方便测试 */
    public static GetUnitTypeId_L(unitObj:any,dv:number | undefined):number{
        if(!EnvConfig.devMod) return GetUnitTypeId(unitObj)
        //A001->1093677105
        return dv || 1093677105 || GetUnitTypeId(unitObj)
    }


    /**dev环境替代 GetItemTypeId 方便测试 */
    public static GetItemTypeId_L(item:any,testResultVal?:number | undefined):number{
        if(!EnvConfig.devMod) return GetItemTypeId(item)
        //I01O->1227895119
        return testResultVal || 1227895119 
    }


    /**dev环境替代 GetItemTypeId 方便测试 */
    public static CreateTrigger_L():trigger | any{
        if(!EnvConfig.devMod) return CreateTrigger()
        //I01O->1227895119
        return {}
    }

    public static RandomInt_L(lowBound:number,hightBound:number):number{
        if(!EnvConfig.devMod) return GetRandomInt(lowBound,hightBound)
        //I01O->1227895119
        //增加一个随机因子
        math.randomseed(os.time())
        return Math.floor(Math.random() * hightBound) + lowBound
    }



    public static CreateEffectOnce(u?:unit,effectPath?:string,addPit?:AttachPointsType):void{
        if(!EnvConfig.devMod) {
            if(u!=undefined && effectPath!=undefined && addPit!=undefined){
                DestroyEffect(AddSpecialEffectTarget(effectPath, u, addPit))
            }
            return
        } 
        //console.log("特效",effectPath)
    }
    
    /**对单位造成附加穿透的伤害 */
    // public static UnitDamageTargetWithIgX_LXXXXX(aux:UnitX,bunit:unit,dmgv:number,isAdditEffDmg:boolean,cir:boolean,igrDefMul:number,dmgTypeKey:DmgTypeKey):void{
    //     if(!EnvConfig.devMod){
    //         if (igrDefMul>0 ){
    //             // 伤害转化为  忽略护甲部分+护甲穿透部分
    //             //let eIgrDmg=dmgv*(1+IgrMul/100)
    //             //let eDefDmg=dmgv-eIgrDmg
    //             UnitDamageTarget(aux.unit, bunit, dmgv*(igrDefMul/100), false, false, ConvertAttackType(DMG_TYPE_CONFIG[dmgTypeKey].cj_atktype), ConvertDamageType(DMG_TYPE_CONFIG[dmgTypeKey].cj_dmgtype), WEAPON_TYPE_WHOKNOWS())
    //          }
    //          UnitDamageTarget(aux.unit, bunit, dmgv*(1-igrDefMul/100), false, false,ConvertAttackType(DMG_TYPE_CONFIG[dmgTypeKey].cj_atktype) , DAMAGE_TYPE_NORMAL(), WEAPON_TYPE_WHOKNOWS())
    //          return 
    //     }
    //     if (igrDefMul>0 ){
    //         console.log(aux.name+" ",dmgTypeKey,isAdditEffDmg?"攻击特效":"技能","造成",cir?"[暴击]":"[非暴击]","伤害:",(dmgv*(1-igrDefMul/100)),",穿甲:",dmgv*(igrDefMul/100))
    //     }else{
    //         console.log(aux.name+" ",dmgTypeKey,isAdditEffDmg?"攻击特效":"技能","造成",cir?"[暴击]":"[非暴击]","伤害:",(dmgv))
    //     }
        
    // }

    public static JAPI_EXSetEventDamage(v:number ):void{
        if(!EnvConfig.devMod){
            EXSetEventDamage(v)
            return
        }
        console.log("japi修改平砍伤害为:",v)
    }


    //TODO
    public static FontN_L(msg:string,u:unit,RGBA:number[]):void{
        if(!EnvConfig.devMod) return 
         console.log(msg)
    }

    public static NumberToString_L(v:number):string{
        if(!EnvConfig.devMod) return tostring(math.floor(v))
        return v+""
    }


    /**
     * 创建并且运行一个timer
     * @param intervalMillSec 间隔（毫秒）
     * @param callback 回调函数
     * @param luaTimerRunMaxTimes 只有lua测试环境才会使用的参数 方便控制timer启停
     * @returns 
     */
    public static CreateTimer_L(intervalMillSec:number,callback:Function,luaTimerRunMaxTimes?:number):any{
        if(!EnvConfig.devMod){
            let t=CreateTimer()
            TimerStart(t,intervalMillSec/1000,true,()=>{callback()})
            return t
        }

        let luaTimer=new LuaTimer(callback);
        luaTimer.runTimer(intervalMillSec,luaTimerRunMaxTimes)
        return luaTimer
       //return setInterval(callback, intervalMillSec)

    }

    public static DestroyTimer_L(timer:any){
        if(!EnvConfig.devMod) {
            DestroyTimer(timer)
            return
        }
        //clearInterval(timer)
        (timer as LuaTimer).destroyTimer()
    }

    /**
     * 获取技能释放目标点坐标
     * （有判断单位目标/点目标逻辑）
     * @returns {'x':number,'y':number}
     */
    public static getSpellTargetXY():{'x':number,'y':number}{
        if(!EnvConfig.devMod) {
          let bunit=GetSpellTargetUnit()
          if(bunit!=null){
            //是单位目标
            return {x:GetUnitX(bunit),y:GetUnitY(bunit)}
          }else{
            //是点目标
            return {x:GetSpellTargetX(),y:GetSpellTargetY()}
          }      
        }
        return {x:0,y:0}
    }

    public static getUnitFacing(u:unit):number{
        if(!EnvConfig.devMod) {
            return GetUnitFacing(u)
        }
        return 0
    }

    /**
     * 为单位添加技能并且设置技能等级
     * @param u 
     * @param skillIdStr 
     * @param lvl 参数为空 默认1级
     * @returns 
     */
    public static UnitAddAbilityWithLvl(u:unit,skillIdStr:string,lvl?:number){
        if(!EnvConfig.devMod) {
            let skillId=L_Math.ID2I(skillIdStr)
            UnitAddAbility(u,skillId)
            if(lvl!=undefined){
                SetUnitAbilityLevel(u,skillId,lvl)
            }
            return
        }
        console.log("单位",u,"添加技能[",skillIdStr,']等级为:',lvl)
    }


    /**
     * 设置单位的技能等级
     * @param u 
     * @param skillIdStr 
     * @returns 
     */

    public static UnitSetAbilityLvl(u:unit,skillIdStr:string,lvl:number){
    if(!EnvConfig.devMod) {
        let skillId=L_Math.ID2I(skillIdStr)
        SetUnitAbilityLevel(u,skillId,lvl)
        return
    }
    console.log("单位",u,"设置技能[",skillIdStr,']等级为:',lvl)
    }

    /**
     * 移除单位的技能
     * @param u 
     * @param skillIdStr 
     * @returns 
     */

    public static UnitRemoveAbility(u:unit,skillIdStr:string){
        if(!EnvConfig.devMod) {
            UnitRemoveAbility(u,L_Math.ID2I(skillIdStr))
            return
        }
        console.log("单位",u,"移除技能[",skillIdStr,']')
    }



}